data Board = Board [[Square]] Turn
instance Show Board where
    show (Board brd _) = showBoard brd

data Square = Empty | Black | White deriving Eq
instance Show Square where
    show Empty = "[ ]"
    show Black = "[B]"
    show White = "[W]"
      
data Turn = BlackTurn | WhiteTurn deriving (Show,Eq)

--Functions for displaying the game board
printBoard :: [[Square]] -> IO()
printBoard board = do
    putStrLn $ showBoard board
    return()

showBoard :: [[Square]] -> String
showBoard [] = ""
showBoard (x:xs) = (printLine x) ++ "\n" ++(showBoard xs)

printLine :: [Square] -> String
printLine [] = ""
printLine (x:xs) = show x ++ " " ++ (printLine xs)


--Functions for starting the game
startBoard :: Integer -> Board
startBoard height = Board [[chooseSquare height x y | x <- [1..height]] | y<-[1..height]] BlackTurn

chooseSquare :: Integer -> Integer -> Integer -> Square
chooseSquare height x y
    | (height `div` 2) == x && (height `div` 2) == y = Black
    | (height `div` 2)+1 == x && (height `div` 2)+1 == y = Black
    | (height `div` 2) == x && (height `div` 2)+1 == y = White
    | (height `div` 2)+1 == x && (height `div` 2) == y = White
    | otherwise = Empty

--Functions for determining if a move is proper, or if a square should be flipped
--Fix from here down to use Board data type
isCapture :: Integer -> Integer -> Integer -> Integer -> Board -> [(Integer,Integer)]
isCapture x y dx dy (Board board turn)
  | (x >=(length board)-1) || (y>=(length board)-1) = []
  | ((board !! x) !! y) /= Empty = []
  | ((board !! (x+dx)) !! (y+dy)) == turn = []
  | otherwise = isCapture' (x) (y) dx dy board turn []

isCapture' x y dx dy board turn xs
  | (x >=(length board)-1) || (y>=(length board)-1)= []
  | ((board !! (x+dx)) !! (y+dy)) == turn = ((x,y):xs)
  | ((board !! (x+dx)) !! (y+dy)) == Empty = []
  | otherwise = isCapture' (x+dx) (y+dy) dx dy board turn (((x+dx),(y+dy)):xs)

{-
isCapture x y dx dy board turn
  | (x >=(length board)-1) || (y>=(length board)-1) = []
  | ((board !! x) !! y) /= Empty = []
  | ((board !! (x+dx)) !! (y+dy)) == turn = []
  | otherwise = isCapture' (x) (y) dx dy board turn

isCapture' x y dx dy board turn
  | (x>=(length board)-1) || (y>=(length board)-1) = []
  | ((board !! (x+dx)) !! (y+dy)) == turn = [(x,y)]
  | ((board !! (x+dx)) !! (y+dy)) == Empty = []
  | otherwise = isCapture' (x+dx) (y+dy) dx dy board turn
-}

--Functions that are in the move-making process
toUpdate board turn x y =
  (isCapture x y 1 0 board turn)++(isCapture x y (-1) 0 board turn)++(isCapture x y 0 1 board turn)++(isCapture x y 0 (-1)  board turn)++(isCapture x y 1 1 board turn)++(isCapture x y 1 (-1) board turn)++(isCapture x y (-1) 1 board turn)++(isCapture x y (-1) (-1) board turn)



blackSquares board = [[if (((board !! x) !! y) == Black) then (x,y) else (-1,-1) | x <- [0..(length board)-1]] | y<-[0..(length board)]]

whiteSquares board = [[if (((board !! x) !! y) == White) then (x,y) else (-1,-1) | x <- [0..(length board)]] | y<-[0..(length board)]]

--updateBoard board turn x y = updateBoardHelper board turn (toUpdate board turn x y)  
--updateBoardHelper board turn [] = board
--updateBoardHelper board turn (l:lst) = updateBoardHelper (updateAt board (fst l) (snd l) turn) turn lst
updateHelper board turn [] = board
updateHelper board turn (x:xs) = updateHelper (updateAt board (fst x) (snd x) turn) turn xs
updateBoard board turn x y = updateHelper board turn (toUpdate board turn x y)


updateAt :: [[Square]] -> Int -> Int -> Square -> [[Square]]
updateAt board x y sqr = [[if x == a && y == b then sqr else getSquareAt board a b | a <- [0.. (length board)-1]] | b<-[0.. (length board)-1]]

getSquareAt :: [[Square]] -> Int -> Int -> Square
getSquareAt board x y = ((board !! y) !! x)

empties board = [ x | x<-[0..length board -1], Empty `elem` board !! x]
   
whoWon board =
    if length (empties board) > 0 then Empty
    else let pnts = score board
         in
           if fst pnts > snd pnts then Black
           else White

score board = scoreHelp board 0 0

scoreHelp [] bpnts wpnts = (bpnts,wpnts)
scoreHelp (x:xs) bpnts wpnts =
    let (lstb,lstw) = ([y | y <- x, y == Black],[z | z <- x, z == White])
    in scoreHelp xs (bpnts+(length lstb)) (wpnts+(length lstw))

